查看原文
其他

用 AI 打造有无穷变化的人生重开模拟器

ElfeXu 南瓜博士 2023-09-17

下午,prompt 爱好者的群里,刘海同学写了长长的文章分享他的 mixcode 伪代码 prompt 设计。作为一名爱把代码写进 prompt 的工程师,刘同学的文章看起来是相当过瘾呀。不过呢,我觉得 prompt 还可以更“伪”一些,要以让非程序员也能轻松读懂为目标

而且,代码越“伪”越像自然语言,AI 自由发挥的空间就更大。口说无凭,我们写个游戏看看吧。

比如,曾经风靡一时的人生重开模拟器。

先偷懒写个没有用到伪代码的版本

向上滑动阅览


# game

- name: 人生重开模拟器

- version: 0.1

- description: 根据初始设定,逐年为玩家生成当年事件,让玩家通过游戏体验无穷种人生


# rule

按如下步骤运行游戏

- 分配属性:总计20点,随机分配给颜值、智力、体质、家境、快乐,每个属性最多10点最少1点

- 自动生成设定:设定玩家的性别、出生地点、父母兄妹等成长环境

- 重复如下步骤,直到死亡事件发生

  - 玩家年龄+1

  - 随机生成和玩家有关的一个事件,事件要符合玩家当前的年龄和属性值

  - 输出事件内容

  - 计算事件影响

  - 更新属性值

- 对玩家一生的故事做总结评价,为玩家撰写墓志铭


现在请开始游戏


0 岁:你是一个女孩,出生在贫穷的西北山村。你的父母都是老实的农民。(颜6 智6 体4 家1 乐3)

1 岁:家里的枣子大丰收。(颜 6 智6 体4 家3 乐5)

2 岁:你摔沟里摔断了腿床上躺了半年。(颜5 智7 体2 家1 乐2)

3 岁:隔壁家的王二买了彩电,你很羡慕,经常去他家看动画片。(颜6 智7 体4 家1 乐3)

……


生成结果有点儿意思

但所有的事件都是关于玩家自身的,范畴也相对比较单调。我们来尝试写个复杂一点的版本教 GPT 如何生成更丰富的事件。(估计这一步在上一个版本的 pompt 里直接加思维链也能搞定,但稳定性比定会差,也不利于后续扩充更复杂的功能。所以,还是用上伪代码。)

向上滑动阅览


# game

- name: 人生重开模拟器

- version: 0.2

- description: 根据初始设定,逐年为玩家生成当年事件,让玩家通过游戏体验无穷种人生


# rule

按如下步骤运行游戏

- 初始化

- 自动生成设定:设定玩家的性别、出生地点、父母兄妹等成长环境

- 根据设定分配属性:总计20点,分配给颜值、智力、健康、富裕、快乐,每个属性最多10点最少1点


- 重复如下步骤,直到死亡事件发生

- 玩家年龄+1

- 随机生成和玩家有关的一个事件,事件要符合玩家当前的年龄和属性值

- 输出事件内容

- 计算事件影响并更新属性值

- 如果玩家已经死亡

- 对玩家一生的故事做总结评价,为玩家撰写墓志铭



# code

<print:$player, $event>

  //以如下格式打印

  **{$player.age} 岁** {$event} (颜{$player.beautiful} 智{$player.smart} 健{$player.healthy} 富{$player.rich} 乐{$player.happy})

  $events.append($event)


<init_attributes:$player, $event>

   //根据 $event 为 $player 分配颜值、智力、健康、富裕、快乐属性,

   //每个属性最多10点最少1点,总和为 20 点

   //例如贫穷山村的女孩属性值可以是 ($player.beautiful=6, $player.smart=6 $player.healthy=4 $player.rich=1 $player.happy=3)


<initialize>

  //设定玩家的性别、出生地点、父母兄妹等成长环境

  $event = 根据玩家设定描述出生信息 //例如 “你是一个女孩,出生在贫穷的西北山村。你的父母都是老实的农民”

  $player = new Player()

  $player.age = 0

init_attributes($player, $event) 

  print<$player, $event>


<generate_event:$player>

  $obj = [你 | 你的父母亲戚 | 你的同学朋友或同事 | 和你生活在同一个地方的陌生人 | 遥远地方的陌生人 ]

  $domain = [健康 | 生活 | 学习 | 工作 | 娱乐 |  体育 | 社会新闻 | 国家大事 ]

  $feeling = [强烈负面 | 负面 | 中性 | 正面 | 强烈正面 ] 

  根据 $player.age 和 $player.beautiful|smart|healthy|rich|happy,为 $obj 在 $domain 领域撰写一则 $feeling 的事件

  返回 $event

  //例如 当 $player.age = 5 时 

  //$obj=你的父母亲戚, $domain = 生活, $feeling = 强烈负面,则可以有   $event=你的妈妈做饭时不小心引发火灾,厨房和你的卧室被烧毁了

  //$obj=社会新闻,$domain = 体育, $feeling = 正面,则可以有 贵州乡村超级杯足球赛引发大众关注,也激起了你踢球的热情


<update_attributes:$player, $event>

  //根据 $event 对玩家属性进行调整

  //例如 你的妈妈做饭时不小心引发火灾,厨房和你的卧室被烧毁了

  $player.rich -= 3

  $player.happy -=2

  $player.health -=1



<write_summary:$player, $events>

  根据 $player 最终状态,和历年发生的 $events,写一篇墓志铭并打印


<run>

  $events = [] //用于记录所有事件

  $player = <initialize>

  重复执行最多200次:

  $player.age += 1

  $event = <generate_event:$player>

  update_attributes($player, $event) 

  <print: $player, $event>

    if $event 表明玩家已死亡: 

       <write_summary:$player> 

       <exit>


---


请注意:你需要**完整**打印玩家的全部生命历程。如果太长了,你可以在打印10条之后休息一会儿,等我说继续你再继续


<run>


我并没有费力气去告诉 GPT 什么是函数什么是调用参数,直接写,GPT 就能认识。

生成事件的关键在于告诉 GPT 要根据玩家属性,为 $obj 在 $domain 领域撰写 $feeling 的事件

结果是这样的:

事件可能是丰富了一些,但好像也没那么明显。生成事件用的参数没那么随机,也怪不得 GPT,它靠语言推测下一个词,要推导到远方的陌生人就太难啦。

这时候我们可以使用真正的代码来生成随机数。以下是第三个版本:

向上滑动阅览


# game

- name: 人生重开模拟器

- version: 0.3

- description: 根据初始设定,逐年为玩家生成当年事件,让玩家通过游戏体验无穷种人生


# rule

按如下步骤运行游戏

- 初始化

- 分配属性:总计20点,分配给颜值、智力、健康、富裕、快乐,每个属性最多10点最少1点

- 根据属性值完成设定:设定玩家的性别、出生地点、父母兄妹等成长环境


- 重复如下步骤,直到死亡事件发生

- 玩家年龄+1

- 随机生成和玩家有关的一个事件,事件要符合玩家当前的年龄和属性值

- 输出事件内容

- 计算事件影响并更新属性值

- 如果玩家已经死亡

- 对玩家一生的故事做总结评价,为玩家撰写墓志铭


# definition

<func: $args...> 表示在自然语言环境中模拟运行,不需要真的写成 python 代码,光通过思考来模拟运行

@@@func: $args... @@@ 表示需要打开 code environment 执行 python 代码得到结果的函数

在程序开始之前,我会请你先定义 << >> 的函数,以便后续游戏运行


# code:在 code environment 里定义 python 函数并执行 

@@@random:$choices@@@:

  //$choices 是一个 {key_string:possibility, }的字典

  //根据各个key 的 possibility 概率,生成随机数,并返回对应的 key_string


@@@init_player@@@

   //创建 $player 并设置为全局变量

   $player.age = 0

   为 $player 分配颜值 $beautiful、智力 $smart、健康 $healthy、富裕 $rich、快乐 $happy 属性,

   每个属性最多10点最少1点,总和为 20 点

   return $player


# non-code:通过思考模拟执行,不需要 python 环境

<log:$player, $event>

  //以如下格式打印

  **{$player.age} 岁** {$event} (颜{$player.beautiful} 智{$player.smart} 健{$player.healthy} 富{$player.rich} 乐{$player.happy})

  $events.append($event)


<birth_event:$player>

  //设定玩家的性别、出生地点、父母兄妹等成长环境

  $event = 根据玩家设定描述符合属性值分配的出生信息,包含玩家性别、出生地点、家庭条件等 

  return $event


<annual_event:$player>

$event = 根据 $player.age 和 $player.beautiful|smart|healthy|rich|happy,为 $obj 在 $domain 领域撰写一则 $feeling 的事件

  //例如 

  //$obj=你的父母亲戚, $domain = 生活, $feeling = 强烈负面,则可以有 $event=你的妈妈做饭时不小心引发火灾,厨房和你的卧室被烧毁了

  //$obj=社会新闻,$domain = 体育, $feeling = 正面,则可以有 贵州乡村超级杯足球赛引发大众关注,也激起了你踢球的热情

  返回 $event 


<update_attributes:$player, $event>

  //根据 $event 对玩家属性进行调整

  //例如 你的妈妈做饭时不小心引发火灾,厨房和你的卧室被烧毁了,则需要进行的调整是

  //$player.rich -= 3

  //$player.happy -=2

  //$player.health -=1


<write_summary:$player, $events>

  根据 $player 最终状态,和历年发生的 $events,写一篇墓志铭并打印



# run

  <OPEN code environment>

    定义 @@@random:$choices@@@ 函数

    定义 @@@init_player@@@ 函数

  <CLOSE code environment>

  

  $events = [] //用于记录所有事件

  <OPEN code environment>

  $player = @@@init_player@@@

  <LOSE code environment>

  $event = <birth_event:$player>

  <log:$player, $event>

  

  [REPEAT BEGIN]

$player.age += 1

    <OPEN code environment>

      $obj = @@@random:{你:10,你的父母亲戚:5,你的同学朋友或同事:3,和你生活在同一个地方的陌生人:2,遥远地方的陌生人:1}@@@

    $domain = @@@random:{健康:2,生活:3,学习:3,工作:3,娱乐:2,体育:1,社会新闻:2,国家大事:1}@@@

    $feeling = @@@random:{强烈负面:1,负面:3,中性1,正面:2,强烈正面:1@@@

  <CLOSE code environment>

    $event = <annual_event:$player, $obj, $domain, $feeling>

  update_attributes($player, $event) 

    log<$player, $event>

  [IF $event 表明玩家已死亡 BEGIN]

       <write_summary:$player, $events> 

       [REPEAT BREAK]

[IF END]

[REPEAT END]


---

请用中文进行游戏。只需要输出 log 的结果,不需要其它任何解释。

现在请开始。


run

我定义了两种不同的“代码”

在刘海的 mixcode 里,代码部分写的是真实的代码。但其实不用这么麻烦,让 code interpreter 帮我们写就可以。这部分我描述了两个函数

在最后 #run 模块首先让 GPT 生成函数定义

执行时是这样的(呃,复制图片时才发现 GPT 写的代码有 bug 呢,看来得改进……)

对于不应该在 code interpreter 环境运行的,给出自然语言占比很高的伪代码描述,并要求“通过思考模拟执行”

log 函数也用伪代码,是因为这样不需要打开代码运行结果就能看到,显示效果会好一些
另几个函数,则是必须用自然语言进行思考,python 代码的 hard-code 是搞不定“生成事件”或者“根据事件判断属性值变化”的

最后,把这些函数和伪函数拼装起来,需要用 python 环境的就通过 <OPEN/CLOSE code environment>标明。

继续运行的结果是这样的:

向上滑动阅览

1岁


2岁


3岁


4岁


5岁


6岁


7岁


8岁


9岁——openai 又没响应了,先告一段落吧


这里有挺多可圈可点的内容。

例如两岁时抽到遥远地方陌生人的中性的工作事件,GPT 能编出看到人们在高楼大厦工作的事件(要记得玩家出生在农村呢),并且认为这个事件会让玩家智力加 1。这也太合理了吧。

六岁孩子的工作是帮父母干农活,也不错。

可惜今晚的 OpenAI 实在太不稳定了,频繁遭遇报错(要不然我也不会写到现在 ),实在是等不到玩家的墓志铭。


其实还有很多要改进的事项。迫不及待先发出来,期待大家一起琢磨一起玩。

功能改进:
1. 开局的时候可以让玩家选择天赋卡。(可以通过在 code-interpreter 里上传 天赋 excel 文件来实现)
2. 生成事件可以用随机词汇(上传的词汇文件可以靠 GPT 生成)来提升丰富性,甚至可以生成一些梗,来让游戏更有趣。
3. 当某些事情发生时,添加标志性成就。

记忆力提升:
1. 创建一个 dataframe 保存玩家每年的事件、关键词以及玩家状态更新,以便最后能写出精彩的墓志铭。

稳定性提升:
1. 将 GPT 生成的 python 代码保存为 .py 文件,上传并要求直接执行 .py 来定义函数,避免实时生成的函数有 bug。
2. 对 prompt 格式做进一步完善。今天的还是糙了点,各种分割符号、函数标记用得有点乱,因而 GPT 执行有时会犯傻,无视我的要求,去 hard-code  birth_event 等函数。
3. 今天 GPT 也无视了 “只需要输出 log 的结果,不需要其它任何解释。” 的要求。这个问题我在之前玩别的 prompt 时也常遇到。不知哪位朋友可以有稳定的解决方案。

我可能得周末才有时间改进它了。期待有小伙伴能抢先做出有趣的重开模拟器呀。祝大家玩得开心。


----

以下是我的各种 code interpreter 花式玩法,邀请你来一起玩。请记得关注转发点赞点在看哦。

当 AI 开始自动思考和行动——让 GPT 左右互搏会发生什么
我敢肯定你没这么玩过 GPT
GPT 上神器 Code Interpreter 的三大超级特性
深度拆解天花板级复杂的提示词 ——什么可照搬什么不要学
平生第一次写小说获奖,是AI帮我的!
看!AI 预测绘制的未来 AI 工程师能力要求与热度图

刘海的伪代码提示词介绍
https://nanfangshaonian.feishu.cn/wiki/YhNdws9LCi1JxGkpJ8dcXB3Gnih?from=from_copylink

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存